home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / reform16.zip / REFORMAT.IN5 < prev    next >
Text File  |  1990-03-03  |  42KB  |  1,151 lines

  1. {-------------------- REFORMAT.IN5 -------------------------------------------}
  2. {Disk, FAT, directory, misc. routines}
  3. {v1.6 Rewrote Check_DOS_Version to permit user override
  4.  of precautionary abort for DOS versions above v3.10
  5. }
  6.  
  7. PROCEDURE ResetDisk;
  8.   { flush buffers that weren't written   }
  9.   BEGIN
  10. (*  In Turbo:
  11.     Register.ah := $0D;
  12.     msdos(Register);
  13. *)
  14.     InLine(
  15.   $B4/$0D   {  mov  ah,$0D  ;reset disk}
  16.   /$CD/$21  {  int  $21}
  17. );
  18.   END;   { of ResetDisk }
  19.  
  20.  
  21. PROCEDURE ResetSubdirectory;
  22.   { DOS might not remember }
  23. {
  24.   The directory information DOS provided us with does not contain the
  25.   driveletter, nor starts it with a backslash.
  26. }
  27.   BEGIN
  28.     Move(CurrentDirectory[0], CurrentDirectory[3], 61);
  29.     CurrentDirectory[0] := DriveLetter;
  30.     CurrentDirectory[1] := ':';
  31.     CurrentDirectory[2] := '\';
  32. (* in Turbo:
  33.     Register.ah := $3B;
  34.     Register.ds := Seg(CurrentDirectory);
  35.     Register.dx := Ofs(CurrentDirectory);
  36.     MSDos(Register);
  37. *)
  38.     Inline(
  39.   $B4/$3B                {mov  ah,$3B}
  40.   /$BA/>CURRENTDIRECTORY {mov  dx,>CurrentDirectory}
  41.   /$CD/$21               {int  $21}
  42. );
  43.   END;   { of ResetSubDirectory                 }
  44.  
  45. {----------------------- general disk   I/O routines -------------------------}
  46.  
  47. PROCEDURE Read_Write_Sectors(sectorNumber, numberOfSectors : Word;  {v1.6 INTEGER;}
  48.                              action : Disk_Activity);
  49.   VAR
  50.     intNr : INTEGER;
  51.  
  52.   FUNCTION CarryFlag: BOOLEAN;
  53.     BEGIN
  54.       CarryFlag := Register.flags AND $01 <> 0;
  55.     END;                                 { of CarryFlag }
  56.  
  57.   BEGIN
  58.     WITH Register DO REPEAT
  59.       al := driveNumber;
  60.       cx := numberOfSectors;
  61.       dx := sectorNumber;
  62.       ds := Seg(DTAddress^);
  63.       bx := Ofs(DTAddress^);
  64.       IF action = reading
  65.       THEN BEGIN
  66.         intNr := $25;
  67.         NrStr := 'Error Reading Disk....';
  68.       END
  69.       ELSE BEGIN
  70.         intNr := $26;
  71.         NrStr := 'Error Writing Disk....';
  72.         AlreadyWritten := TRUE;     { set it now because the first write
  73.                                       might succeed partially! }
  74.       END;
  75.       int2526(intNr);                  { 25H = read, 26H = write }
  76.       IF CarryFlag THEN BEGIN
  77.         S40 := 'Enter A (abort), R (retry)';
  78.         IF NOT AlreadyWritten THEN BEGIN
  79.           WriteWarning('No data lost!');
  80.           WriteError(NrStr);
  81.           Legals := 'AR';
  82.         END
  83.         ELSE BEGIN
  84.           WriteError('Probably loss of data!');
  85.           WriteDisaster(NrStr);
  86.           S40 := S40 + ', I(gnore)';
  87.           Legals := 'ARI';
  88.         END;
  89.  
  90.         REPEAT
  91.           Getinput(S40,Instr);
  92.         UNTIL POS(Instr,Legals) <> 0;
  93.  
  94.         IF Instr = 'A' THEN BEGIN
  95.           GotoXY(1,24); WRITELN;  {leave the screen for him or her }
  96.           HALT;
  97.         END
  98.         ELSE BlankFields;
  99.       END;
  100.     UNTIL NOT CarryFlag;
  101.   END;  { of Read_Write_Sectors }
  102.  
  103.  
  104. PROCEDURE ReadCluster(clusterNumber: word);
  105.   VAR   sectorNumber: word;
  106.   BEGIN
  107. (* v1.6
  108.     sectorNumber := W_add(W_mul( clusterSize, clusterNumber - 2 ),
  109.                     firstDataSector);
  110. *)
  111.     sectorNumber := (clusterSize * (clusterNumber-2)) + firstDataSector; {v1.6}
  112.  
  113.     Read_Write_Sectors(sectorNumber, clusterSize,reading);
  114.   END;  { of ReadCluster }
  115.  
  116.  
  117. PROCEDURE WriteCluster(clusterNumber: word);
  118.   VAR   sectorNumber: word;
  119.   BEGIN
  120. (* v1.6
  121.     sectorNumber := W_add(W_mul( clusterSize, clusterNumber - 2 ),
  122.                     firstDataSector);
  123. *)
  124.     sectorNumber := (clusterSize * (clusterNumber-2)) + firstDataSector; {v1.6}
  125.  
  126.     Read_Write_Sectors(sectorNumber, clusterSize, writing);
  127.   END;  { of WriteCluster }
  128.  
  129.  
  130. {----------------------- disk information   routines -------------------------}
  131.  
  132. PROCEDURE ReadBootSector(VAR DTArea: Buffer);
  133. {
  134.   Read the bootsector from disk.
  135. }
  136.   VAR
  137.     BootInfo:          Boot Absolute DTArea;
  138.   BEGIN
  139.     WriteLog('Reading Bootsector.');
  140.     Read_Write_Sectors(0, 1, reading);
  141.     FOR count := 0 TO 7 DO
  142.       OEM[count]       := Bootinfo.OEM[count];
  143.     totalSectors       := Bootinfo.totalSectors;
  144.     trackSize          := Bootinfo.trackSize;
  145.     hiddenSectors      := Bootinfo.hiddenSectors;
  146.   END;  { of ReadBootSector }
  147.  
  148.  
  149. PROCEDURE GetInformation;
  150. {
  151.   Ask DOS for information about the specified drive.
  152.   If we have an error return code from DOS we assume
  153.   that the disk specified was invalid.
  154.   We are using a number of DOS int 21H functions:
  155.  
  156.   1) function 19H : returns current default drive in al: 0 = a, ..
  157.   2) function 32H : ! undocumented function !
  158.                     returns a parameter table which is laid out
  159.                     in the type Parameter_Table.
  160.   3) function 36H : several, but we only use the disk free space
  161.   4) function 47H : current working directory.
  162.  
  163.   the remainder of the information we want to have or need, we find
  164.   in the disks bootrecord and in the FAT (bad space and used space).
  165. }
  166.   VAR
  167.     ValidDrive:   BOOLEAN;
  168.     Parms:        Parms_32;
  169.   BEGIN
  170.     IF Instr = ' '
  171.     THEN GetInput('Enter drive letter',Instr);
  172.     WriteLog('Reading Disk Information');
  173. {
  174.     get current disk: MS-DOS function call 19h
  175.     information is returned in AL: 0 = A, 1 = B, etc.
  176. }
  177.     WITH Register DO BEGIN
  178. (* in Turbo:
  179.       ah := $19;                         { DOS returns the default drive in al  }
  180.       MSDos(Register);                   { as: 0 = A, 1 = B .... }
  181.       defaultDrive := al;
  182. *)
  183.       Inline(
  184.   $B4/$19                {mov  ah,$19}
  185.   /$CD/$21               {int  $21}
  186.   /$A2/>DEFAULTDRIVE     {mov  [>defaultDrive],al}
  187. );
  188.       ValidDrive   := FALSE;
  189.  
  190.       REPEAT                             { keep trying until a good letter }
  191.         IF ORD(Instr) < 64 THEN Instr := CHR($FF);
  192.         DriveLetter := UpCase(Instr);
  193.         driveNumber := ORD(DriveLetter) - 64; { A = 65, so A = 1, B = 2, ...... }
  194.         ah := $36;
  195.         dl := driveNumber;               { must be 0 = default, 1 = A, 2 = B .. }
  196.         MSDos(Register);
  197.         IF ax <> $ffff THEN ValidDrive := TRUE
  198.         ELSE BEGIN
  199.           WriteWarning('Invalid driveletter!');
  200.           GetInput('Enter new letter',Instr);
  201.           WriteWarning(' ');
  202.         END;
  203.       UNTIL ValidDrive;
  204.  
  205.       freeClusters :=          bx;       { we can find that only here }
  206. {
  207.     In case the drive to be reformatted has a current working directory
  208.     DOS may lose track of the current working directory. So we will get
  209.     the current working directory and will tell DOS what it is, when
  210.     we are done.
  211. }
  212.       dl := driveNumber;                 { must be 0 = default, 1 = A, 2 = B .. }
  213.       ds := Seg(CurrentDirectory);
  214.       si := Ofs(CurrentDirectory);
  215.       ah := $47;                         { DOS returns current working directory}
  216.       MSDos(Register);                   { no error, drive checked before }
  217. {
  218.     We now use the undocumented DOS function call 32H. It was described in the
  219.     May 86 PC Tech Journal article "Finding Disk Parameters" by
  220.     Glenn F. Roberts.
  221. }
  222.       dl := driveNumber;                 { must be 0 = default, 1 = A, 2 = B .. }
  223.       ah := $32;
  224.       MSDos(Register);
  225.       Parms                := Ptr(         ds,          bx);
  226.       sectorSize           := Parms^.sectorSize;
  227.       media                := Parms^.MediaDescriptor;
  228.       numberOfHeads        := SUCC(Parms^.numberOfHeads_1);
  229.       reservedSectors      := Parms^.reservedSectors;
  230.       rootDirSize          := Parms^.rootDirSize;
  231.       numberOfFATs         := Parms^.numberOfFATs;
  232.       fatSize              := Parms^.fatSize;
  233.       clusterSize          := SUCC(Parms^.clusterSize_1);
  234.       firstDataSector      := Parms^.firstDataSector;
  235.       firstDirectorySector := Parms^.firstDirectorySector;
  236.       totalDataClusters    := PRED(Parms^.totalDataClusters_1);
  237. (* v1.6
  238.     BigFAT               := W_cmp(totalDataClusters, Gt, 4086);
  239. *)
  240.       BigFAT             := (totalDataClusters > 4086);  {v1.6}
  241.     END;  {of with Register}
  242.  
  243.     IF BigFAT THEN BEGIN
  244.       unused          := $0000;
  245.       reservedMinimum := $FFF0;
  246.